package com.zone.isle.initializer

import android.app.Application
import android.content.Context
import android.os.Handler
import android.os.Looper
import androidx.startup.Initializer
import com.zone.core.CoreApplication

class CrashInitializer : Initializer<Unit> {

    override fun create(context: Context) {
        CrashHunter.run(context.applicationContext as Application)
    }

    override fun dependencies(): List<Class<out Initializer<*>>> {
        return emptyList()
    }


    object CrashHunter : Thread.UncaughtExceptionHandler {
        @Volatile
        private var uncaughtExceptionHandler: Thread.UncaughtExceptionHandler? = null

        fun run(app: Application) {
            uncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()

            Thread.setDefaultUncaughtExceptionHandler(this)
        }

        override fun uncaughtException(t: Thread, e: Throwable) {

            e.printStackTrace()
            if (t !== Looper.getMainLooper().thread) {
                return
            }
            while (true) {
                try {
                    Handler(Looper.getMainLooper()).postAtFrontOfQueue {
                        try {
                            finishActivityIfNeeded(t, e)
                        } catch (_: Exception) {
                        }
                        Thread.setDefaultUncaughtExceptionHandler(this)
                    }
                    Looper.loop()
                } catch (throwable: Throwable) {
                    throwable.printStackTrace()
                    Thread.setDefaultUncaughtExceptionHandler(this)
                }
            }
        }

        private fun finishActivityIfNeeded(t: Thread, e: Throwable) {
            val elements = e.stackTrace ?: return
            for (i in elements.size - 1 downTo 0) {
                val element = elements[i]
                if ("android.app.ActivityThread" == element.className && "ActivityThread.java" == element.fileName && "performLaunchActivity" == element.methodName) {
                    CoreApplication.finishActivity(element.javaClass)
                    break
                }
            }
        }
    }
}